<?php

namespace pmvc\util;

use ReflectionClass;

class ClassUtil {

	private static $LOADED_CLASS_CACHE	= Array();
	private static $CLASS_ISA_CACHE		= Array();

	/**
	 * Loads a class by it's name returning a {@link ReflectionClass}
	 * for the loaded class.
	 * @param string $className
	 * @return ReflectionClass the loaded class
	 */
	public static function loadClass($className) {
		if (!array_key_exists($className, ClassUtil::$LOADED_CLASS_CACHE)) {
			ClassUtil::$LOADED_CLASS_CACHE[$className] = new ReflectionClass($className);
		}
		return ClassUtil::$LOADED_CLASS_CACHE[$className];
	}
	
	/**
	 * Checks to see if the given $className is a
	 * $classIsA (if it can be cast to the given type).
	 * @param string $className
	 * @param string $classIsA
	 */
	public static function classIsA($className, $classIsA) {
		if (!array_key_exists($className.$classIsA, ClassUtil::$CLASS_ISA_CACHE)) {
			$clazz = ClassUtil::loadClass($className);
			$clazzIsA = ClassUtil::loadClass($classIsA);
			ClassUtil::$CLASS_ISA_CACHE[$className.$classIsA] = ($clazzIsA->isInterface()) 
				? $clazz->implementsInterface($classIsA)
				: $clazz->isSubclassOf($classIsA);
		}
		return ClassUtil::$CLASS_ISA_CACHE[$className.$classIsA];
	}
	
	/**
	 * Checks to see if the given object is a $class.
	 * (if it can be cast to the given type).
	 * @param mixed $obj
	 * @param string $class
	 */
	public static function isInstance($obj, $class) {
		if (!is_object($obj)) {
			return false;
		}
		if ($class!="pmvc\aop\Proxy"
			&& ClassUtil::classIsA(get_class($obj), "pmvc\aop\Proxy")) {
			return ClassUtil::isInstance($obj->getProxiedObject(), $class);
		}
		return is_a($obj, $class);
	}

}


?>